home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 1
/
Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso
/
FILES
/
DEV
/
I-Z
/
TransSkel.cpt
/
TransDisplay.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1987-02-09
|
27KB
|
1,024 lines
{ TransDisplay version 1.0 - TransSkel plug-in module supporting}
{ an arbitrary number of generic display windows with memory.}
{ TransSkel and TransDisplay are public domain, and are written by:}
{ Paul DuBois}
{ Wisconsin Regional Primate Research Center}
{ 1220 Capital Court}
{ Madison WI 53706 USA}
{ UUCP: [allegra,ihnp4,seismo]!uwvax !uwmacc !dubois }
{ ARPA : dubois @ unix.macc.wisc.edu }
{ dubois @ rhesus.primate.wisc.edu }
{ The Pascal Version of TransSkel is public domain and was ported by }
{ Owen Hartnett }
{ Ωhm Software }
{ 163 Richard Drive }
{ Tiverton, RI 02878 }
{ CSNET: omh@cs.brown.edu.CSNET }
{ ARPA: omh%cs.brown.edu@relay.cs.net-relay.ARPA }
{ UUCP: [ihnp4,allegra]!brunix !omh }
{ Psychic Wavelength: 182.2245 Meters (sorry, couldn't resist) }
{ This version of TransDisplay written for Lightspeed Pascal. Lightspeed Pascal}
{ is a trademark of:}
{ THINK Technologies, Inc}
{ 420 Bedford Street Suite 350}
{ Lexington, MA 02173 USA}
{ History}
{ 08/25/86 Genesis. Beta version.}
{ 09/15/86 Changed to allow arbitrary number of windows. Changed}
{ version number to 1.0.}
{ 01/10/87 Ported to LightSpeed Pascal by Owen Hartnett }
{ Ωhm Software, 163 Richard Drive, Tiverton, RI 02878 }
UNIT TransDisplay;
INTERFACE
USES
TransSkelPas;
PROCEDURE SetDWindow (theWind : WindowPtr);
PROCEDURE DisplayString (theStr : str255);
PROCEDURE DisplayHexLong (l : longint);
PROCEDURE DisplayHexInt (i : integer);
PROCEDURE DisplayHexChar (c : char);
PROCEDURE DisplayBoolean (b : Boolean);
PROCEDURE DisplayChar (c : char);
PROCEDURE DisplayInt (i : integer);
PROCEDURE DisplayLong (l : longint);
PROCEDURE DisplayLn;
PROCEDURE DisplayText (theText : Ptr;
len : longint);
FUNCTION GetNewDWindow (resourceNum : integer;
behind : WindowPtr) : WindowPtr;
FUNCTION NewDWindow (bounds : Rect;
title : Str255;
visible : Boolean;
behind : WindowPtr;
goAway : Boolean;
refcon : longint) : WindowPTr;
PROCEDURE FlushDWindow (theWind : WindowPtr;
byteCount : longint);
PROCEDURE GetDWindow (VAR theWind : WindowPtr);
PROCEDURE SetDWindowFlush (theWind : WindowPtr;
maxText, flushAmt : longint);
PROCEDURE SetDWindowNotify (theWind : WindowPTr;
p : ProcPtr);
PROCEDURE setDWindowPos (theWind : WindowPtr;
lineNum : integer);
PROCEDURE SetDWindowStyle (theWind : WindowPtr;
font, size, wrap, just : integer);
FUNCTION GetDWindowTE (theWind : WindowPtr) : TEHandle;
FUNCTION IsDWindow (theWind : WindowPtr) : Boolean;
PROCEDURE TransDisplayInit;
IMPLEMENTATION
{ Display window types, constants, variables.}
CONST
monaco = 4;
TYPE
DIPtr = ^DisplayInfo;
DIHandle = ^DIPtr;
DisplayInfo = RECORD
dWind : WindowPtr; { display window }
dTE : TEHandle; { window text }
dScroll : ControlHandle; { window scroll bar }
dActivate : ProcPtr; { notification procedure }
dMaxText : longint; { max text length }
dFlushAmt : longint; { amount to autoflush }
dNext : DIHandle; { next window structure }
END;
VAR
{ Look at TransDisplayInit procedure for initial values of these variables }
d_font, d_size : integer; { default font }
{ default pointsize }
d_wrap, d_just : integer; { default word wrap (on) }
{ default justification }
d_maxText, d_flushAmt : longint; { default max text allowed }
{ default autoflush amount }
d_activate : ProcPtr; { default notification proc }
{ Lowest allowable values for autoflush characteristics}
d_loMaxText, d_loFlushAmt : longint;
dwList : DIHandle;
{ Variables pertaining to the display window being operated on}
{ (updated, resized, etc.). This window is not necessarily the}
{ same as curDispWind! These variables are synced to the window}
{ with SyncGlobals. }
dispInfo : DIHandle; { info structure }
dispWind : WindowPtr; { the window }
dispTE : TEHandle; { window text }
dispScroll : ControlHandle; { the scroll bar }
dActivate : ProcPtr; { notification procedure }
dMaxText, dFlushAmt : longint; { max text allowed }
{ amount to flush }
{ curDispWind is the current output window.}
{ If curDispWind = nil, output is turned off.}
curDispWind : WindowPtr;
{ -------------------------------------------------------------------- }
{ Miscellaneous Internal (private) Routines }
{ -------------------------------------------------------------------- }
{ Draw grow box of dispWind in lower right hand corner}
PROCEDURE DrawGrowBox;
VAR
oldClip : RgnHandle;
r : Rect;
BEGIN
r := dispWind^.portRect;
r.left := r.right - 15; { draw only in corner }
r.top := r.bottom - 15;
oldClip := NewRgn;
GetClip(oldClip);
ClipRect(r);
DrawGrowIcon(dispWind);
SetClip(oldClip);
DisposeRgn(oldClip);
END;
{ -------------------------------------------------------------------- }
{ Lowest-level Internal (Private) Display Window Routines }
{ -------------------------------------------------------------------- }
{ Get display window info associated with window.}
{ Return nil if window isn't a known display window.}
FUNCTION GetDInfo (theWind : WindowPtr) : DIHandle;
VAR
h : DIHandle;
foundit : Boolean;
BEGIN
h := dwList;
foundit := false;
WHILE (h <> NIL) AND NOT foundit DO
BEGIN
IF h^^.dWind = theWind THEN
BEGIN
GetDInfo := h;
h := NIL;
foundit := true;
END
ELSE
h := h^^.dNext;
END;
IF NOT foundit THEN
GetDInfo := NIL; {make it a nop }
END;
{ Synchronize globals to a display window. theWind must be a legal}
{ display window, with one exception: if theWind is nil, the}
{ variables are synced to the current port. That is safe (and}
{ correct) because:}
{ (i) nil is only passed by display window handler procedures,}
{ which are only called by TransSkel for display window}
{ events.}
{ (ii) TransSkel always sets the port to the window before}
{ calling the handler proc.}
{ Hence, use of the current port under these circumstances}
{ always produces a legal display window.}
{ SyncGlobals is not used in single display mode, because the}
{ globals are all set by SetupDWindow and do not change thereafter.}
PROCEDURE SyncGlobals (theWind : WindowPtr);
VAR
dp : DIPtr;
BEGIN
IF theWind = NIL THEN { use current window }
GetPort(theWind);
dispWind := theWind;
dispInfo := GetDInfo(dispWind);
dp := dispInfo^;
dispScroll := dp^.dScroll;
dispTE := dp^.dTE;
dActivate := dp^.dActivate;
dMaxText := dp^.dMaxText;
dFlushAmt := dp^.dFlushAmt;
END;
{ Calculate the dimensions of the editing rectangle for}
{ dispWind (which must be set properly and is assumed to }
{ the current port). (The viewRect and destRect are the}
{ same size .) Assumes the port , text font and text size are all}
{ set properly. The viewRect is sized so that an integral}
{ number of lines can be displayed in it, i.e., so that a}
{ partial line never shows at the bottom. }
PROCEDURE CalcEditRect (VAR r : Rect);
VAR
f : FontInfo;
lineHeight : integer;
BEGIN
GetFontInfo(f);
lineHeight := f.ascent + f.descent + f.leading;
r := dispWind^.portRect;
r.left := r.left + 4;
r.right := r.right - 17; { leave room for scroll bar + 2 }
r.top := r.top + 2;
r.bottom := r.top + ((r.bottom - (r.top - 2)) DIV lineHeight) * lineHeight;
END;
{ Calculate the dimensions of the scroll bar rectangle for the}
{ window. Make sure that the edges overlap the window frame and}
{ the grow box.}
PROCEDURE CalcScrollRect (VAR r : Rect);
BEGIN
r := dispWind^.portRect;
r.right := r.right + 1;
r.left := r.right - 16;
r.top := r.top - 1;
r.bottom := r.bottom - 14;
END;
{ Calculate the number of lines currently scrolled off}
{ the top.}
FUNCTION LinesOffTop : integer;
VAR
ePtr : TEPtr;
BEGIN
ePtr := dispTE^;
LinesOffTop := (ePtr^.viewRect.top - ePtr^.destRect.top) DIV ePtr^.lineHeight;
END;
{ Highlight the scroll bar properly. This means that it's not}
{ made active if the window itself isn't active, even if}
{ there's enough text to fill the window. }
PROCEDURE HiliteScroll;
VAR
result : integer;
BEGIN
IF (GetCtlMax(dispScroll) > 0) AND (dispWind = FrontWindow) THEN
result := 0
ELSE
result := 255;
HiliteControl(dispScroll, result);
END;
{ Scroll to the correct position. lDelta is the}
{ amount to CHANGE the current scroll setting by.}
{ Positive scrolls the text up, negative down.}
PROCEDURE ScrollText (lDelta : integer);
VAR
lHeight, newLine, topLine : integer;
BEGIN
lHeight := dispTE^^.lineHeight;
topLine := LinesOffTop;
newLine := topLine + lDelta;
IF newLine < 0 THEN
newLine := 0;
IF newLine > GetCtlmax(dispScroll) THEN
newLine := GetCtlMax(dispScroll);
SetCtlValue(dispScroll, newLine);
TEScroll(0, (topLine - newLine) * lHeight, dispTE);
END;
{ Filter proc for tracking mousedown in scroll bar . The code}
{ for the part originally hit is stored in the control 's reference}
{ value by Mouse ( ) before calling this . }
{ Scroll by one line if the mouse is in an arrow. Scroll by a half}
{ window's worth of lines if the mouse is in a page region. }
PROCEDURE TrackScroll (theScroll : ControlHandle;
partCode : integer);
VAR
lDelta, halfPage : integer;
BEGIN
IF partCode = GetCRefCon(theScroll) THEN { still in same part? }
BEGIN
halfPage := ((dispTE^^.viewRect.bottom - dispTE^^.viewRect.top) DIV dispTE^^.lineHeight) DIV 2;
IF halfPage = 0 THEN
halfPage := halfPage + 1;
CASE partCode OF
inUpButton :
lDelta := -1;
inDownButton :
lDelta := 1;
inPageUp :
lDelta := -halfPage;
inPageDown :
lDelta := halfPage;
OTHERWISE
END;
ScrollText(lDelta);
END;
END;
{ Adjust the text in the text record and the scroll bar. This is}
{ called for major catastrophes, such as resizing the window, or}
{ changing the word wrap style. It makes sure the view and}
{ destination rectangles are sized properly, and that the bottom}
{ line of text never scrolls up past the bottom line of the}
{ window, if there's enough to fill the window, and that the}
{ scroll bar max and current values are set properly.}
{ Resizing the dest rect just means resetting the right edge}
{ (the top is NOT reset), since text might be scrolled off the}
{ top (i.e., destRect.top != 0).}
PROCEDURE OverhaulDisplay;
VAR
r : Rect;
nLines, visLines, topLines, scrollLines, lHeight : integer;
{ number of lines in TERec }
{ number of lines displayable in window }
{ number of lines currently scrolled off top }
{ number of lines to scroll down }
BEGIN
CalcEditRect(r);
dispTE^^.destRect.right := r.right;
dispTE^^.viewRect := r;
TECalText(dispTE); { recalc line starts }
lHeight := dispTE^^.lineHeight;
nLines := dispTE^^.nLines;
visLines := (r.bottom - r.top) DIV lheight;
topLines := LinesoffTop;
{ If the text doesn't fill the window (visLines > nLines - topLines),}
{ pull the text down if possible (if topLines > 0). Make sure}
{ not to try to scroll down by more lines than are hidden off the top .}
scrollLines := visLines - (nLines - topLines);
IF (scrollLines > 0) AND (topLines > 0) THEN
BEGIN
IF scrollLines > topLines THEN
scrollLines := topLines;
TEScroll(0, scrollLInes * lHeight, dispTE);
toplines := topLines - scrollLines;
END;
TEUpdate(r, dispTE);
IF nLines - visLines < 0 THEN
SetCtlMax(dispScroll, 0)
ELSE
SetCtlMax(dispScroll, nLines - VisLines);
SetCtlValue(dispScroll, topLines);
HiliteScroll;
END;
PROCEDURE callpnoarg (myProc : ProcPtr);
{ For all the Procedures that are called with no arguments }
INLINE
$205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
$4e90;
PROCEDURE callpBoolean (myBool : Boolean;
myProc : ProcPtr);
{ Two calls use Booleans as one parameter arguments. This procedure handles }
{ both of them. }
INLINE
$205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
$4e90;
{ ---------------------------------------------------------------- }
{ Window Handler Routines }
{ ---------------------------------------------------------------- }
{ When the window comes active, highlight the scroll bar appropriately.}
{ When the window is deactivated, un-highlight the scroll bar.}
{ Redraw the grow box.}
{ Notify the host as appropriate.}
{ Note that clicking close box hides the window, which generates a}
{ deactivate event, so there is no need for a close notifier.}
PROCEDURE Activate (isActive : Boolean);
BEGIN
SyncGlobals(NIL); { sync to current port }
DrawGrowBox;
HiliteScroll;
IF dActivate <> NIL THEN
callpBoolean(isActive, dActivate);
END;
{ Update window. The update event might be in response to a}
{ window resizing. If so, move and resize the scroll bar,}
{ and recalculate the text display.}
{ The ValidRect call is done because the HideControl adds the}
{ control bounds box to the update region - which would generate}
{ another update event! Since everything is redrawn below anyway,}
{ the ValidRect is used to cancel the update.}
PROCEDURE Update (resized : Boolean);
VAR
r : Rect;
BEGIN
SyncGlobals(NIL); { sync to current port }
r := dispWind^.portRect;
EraseRect(r);
IF resized THEN
BEGIN
HideControl(dispScroll);
r := dispScroll^^.contrlRect;
ValidRect(r);
CalcScrollRect(r);
SizeControl(dispScroll, 16, r.bottom - r.top);
MoveControl(dispScroll, r.left, r.top);
OverHaulDisplay;
ShowControl(dispScroll);
END
ELSE
BEGIN
r := dispTE^^.viewRect;
TEUpdate(r, dispTE);
END;
DrawGrowBox;
DrawControls(dispWind); { redraw scroll bar }
END;
{ Handle mouse clicks in window}
PROCEDURE Mouse (thePt : Point;
t : longint;
mods : integer);
VAR
thePart : integer;
oldCtlValue : integer;
BEGIN
SyncGlobals(NIL); { Sync to current port }
thePart := TestControl(dispScroll, thePt);
IF thePart = inThumb THEN
BEGIN
OldCtlValue := GetCtlValue(dispScroll);
IF TrackControl(dispScroll, thePt, NIL) = inThumb THEN
ScrollText(GetCtlValue(dispScroll) - oldCtlValue);
END
ELSE IF thePart <> 0 THEN
BEGIN
SetCRefCon(dispScroll, longint(thePart));
oldCtlValue := TrackControl(dispScroll, thePt, @TrackScroll);
END;
END;
{ Remove the display window from the list, and dispose of it.}
{ Since the clobber procedure is never called except for real display}
{ windows, and since the list must therefore be non-empty, it is}
{ not necessary to check the legality of the window or that the}
{ window's in the list.}
{ Must do SetDWindow (nil) to turn output off, if the window being}
{ clobbered is the current output window.}
PROCEDURE Clobber;
VAR
h, h2 : DIHandle;
keepgoing : Boolean;
BEGIN
SyncGlobals(NIL); { sync to current port }
IF dispWind = curDispWind THEN { is it the first window in list? }
SetDWindow(NIL);
IF dwList^^.dWind = dispWind THEN { found it }
BEGIN
h2 := dwList;
dwList := dwList^^.dNext;
END
ELSE
BEGIN
h := dwList;
keepgoing := true;
WHILE (h <> NIL) AND keepgoing DO
BEGIN
h2 := h^^.dNext;
IF h2^^.dWind = dispWind THEN
BEGIN
h^^.dNext := h2^^.dNext;
keepgoing := false;
END;
h := h2;
END;
END;
DisposHandle(Handle(h2)); { get rid of information structure }
TEDispose(dispTE); { toss text record }
DisposeWindow(dispWind); { toss window and scroll bar }
dispWind := NIL;
END;
{ ---------------------------------------------------------------- }
{ Control Routines }
{ ---------------------------------------------------------------- }
{ Test whether a window is a legal display window or not }
FUNCTION IsDWindow;
BEGIN
IsDWindow := GetDInfo(theWind) <> NIL;
END;
{ Return handle to display window's text record}
FUNCTION GetDWindowTE;
VAR
dInfo : DIHandle;
BEGIN
IF GetDInfo(theWind) = NIL THEN
GetDWindowTE := NIL
ELSE
GetDWIndowTE := dInfo^^.dTE;
END;
{ Change the text display characteristics of a display window}
{ and redisplay it. As a side effect, this always scrolls to the}
{ home position.}
PROCEDURE SetDWindowStyle;
VAR
savePort : GrafPtr;
f : FontInfo;
te : TEHandle;
r : Rect;
BEGIN
IF theWind = NIL THEN { reset window creation defaults }
BEGIN
d_font := font;
d_size := size;
d_wrap := wrap;
d_just := just;
END
ELSE
BEGIN
IF IsDWindow(theWind) THEN
BEGIN
GetPort(savePort);
SyncGlobals(theWind);
SetPort(dispWind);
te := dispTE;
r := te^^.viewRect;
EraseRect(r);
r := te^^.destRect; { scroll home without redrawing }
OffsetRect(r, 0, 2 - r.top);
te^^.destRect := r;
te^^.crOnly := wrap; { set word wrap }
TESetJust(just, te); { set justification }
TextFont(font); { set the font and point size }
TextSize(size); { of text record (this is the }
GetFontInfo(f); { hard part) }
te^^.lineHeight := f.ascent + f.descent + f.leading;
te^^.fontAscent := f.ascent;
te^^.txFont := font;
te^^.txSize := size;
OverhaulDisplay;
SetPort(savePort);
END;
END;
END;
{ Scroll the text in the window so that line lineNum is at the top.}
{ First line is line zero.}
PROCEDURE setDWindowPos;
VAR
savePort : GrafPtr;
BEGIN
IF IsDWindow(theWind) THEN
BEGIN
GetPort(savePort);
SyncGlobals(theWind);
SetPort(dispWind);
ScrollText(lineNum - GetCtlValue(dispScroll));
SetPort(savePort);
END;
END;
{ Set display window activate notification procedure.}
{ Pass nil to disable it.}
PROCEDURE SetDWindowNotify;
VAR
dInfo : DIHAndle;
BEGIN
IF theWind = NIL THEN { reset window creation default }
d_activate := p
ELSE
BEGIN
dInfo := GetDInfo(theWind);
IF dInfo <> NIL THEN
dInfo^^.dActivate := p;
END;
END;
{ Set display window autoflush characteristics}
PROCEDURE SetDWindowFlush;
VAR
dInfo : DIHandle;
BEGIN
IF maxText > longint(32767) THEN
maxText := 32767;
IF maxText < d_loMaxText THEN
maxText := d_loMaxText;
IF flushAmt < d_loFlushAmt THEN
flushAmt := d_loFlushAmt;
IF theWind = NIL THEN
BEGIN { reset window creation defaults }
d_maxText := maxText;
d_flushAmt := flushAmt;
END
ELSE
BEGIN
dInfo := GetDInfo(theWind);
IF dInfo <> NIL THEN
BEGIN
dInfo^^.dMaxText := maxText;
dInfo^^.dFlushAmt := flushAmt;
END;
END;
END;
{ Set which display window is to be used for output. If theWind}
{ is nil, output is turned off. If theWind is not a legal display}
{ window, nothing is done.}
PROCEDURE SetDWindow;
BEGIN
IF (theWind = NIL) OR IsDWindow(theWind) THEN
curDispWind := theWind;
END;
{ Get the WindowPtr of the current output display window. If}
{ output is turned off, this will be nil.}
PROCEDURE GetDWindow;
BEGIN
theWind := curDispWind;
END;
{ Flush text from the window and readjust the display.}
PROCEDURE FlushDWindow;
BEGIN
IF IsDWindow(theWind) THEN
BEGIN
SyncGlobals(theWind);
TESetSelect(longint(0), byteCount, dispTE); { select text }
TEDelete(dispTE); { clobber it }
OverhaulDisplay;
END;
END;
{ Create and initialize a display window and the associated data}
{ structures, and return the window pointer. Install window in}
{ list of display windows.}
PROCEDURE SetupDWindow;
VAR
r : Rect;
savePort : GrafPtr;
dInfo : DIHandle;
BEGIN
GetPort(savePort);
SkelWindow(dispWind, @Mouse, NIL, @Update, @Activate, NIL, @Clobber, NIL, false);
{ the window }
{ mouse click handler }
{ key clicks are ignored }
{ window updating procedure }
{ window activate/deactivate procedure }
{ TransSkel hides window if no close proc }
{ (generates deactivate event) }
{ window disposal procedure }
{ no idle proc }
{ irrelevant since no idle proc }
{ Build the scroll bar. Make sure the borders overlap the}
{ window frame and the frame of the grow box.}
CalcScrollRect(r);
dispScroll := NewControl(dispWind, r, '', true, 0, 0, 0, scrollBarProc, longint(0));
{ Create the TE record used for text display. Use defaults for}
{ display characteristics. Setting window style overhauls}
{ display, so can cancel and update event pending for the window.}
CalcEditRect(r);
dispTE := TENew(r, r);
{ Get new information structure, attach to list of known display}
{ windows.}
dInfo := DIHandle(NewHandle(sizeof(DisplayInfo)));
dInfo^^.dNext := dwList;
dwList := dInfo;
dInfo^^.dWind := dispWind;
dInfo^^.dScroll := dispScroll;
dInfo^^.dTE := dispTE;
SetDWindowNotify(dispWind, d_activate);
SetDWindowFlush(dispWind, d_maxtext, d_flushAmt);
SetDWindowStyle(dispWind, d_font, d_size, d_wrap, d_just);
{ Make window current display output window}
SetDWindow(dispWind);
SetPort(savePort);
END;
{ Create and initialize a display window and the associated data}
{ structures, and return the window pointer. Install window in}
{ list of display windows. In single-window mode, disallow}
{ creation of a new window if one already exists.}
{ The parameters are similar to those for NewWindow. See Inside}
{ Macintosh.}
FUNCTION NewDWindow;
BEGIN
dispWind := NewWindow(NIL, bounds, title, visible, documentProc, behind, goAway, refCon);
SetUpDWindow;
NewDWindow := dispWind;
END;
{ Create and initialize a display window (using a resource) and}
{ the associated data structures, and return the window pointer.}
{ Install window in list of display windows. In single-window}
{ mode, disallow creation of a new window if one already exists.}
{ The parameters are similar to those for GetNewWindow. See Inside}
{ Macintosh.}
FUNCTION GetNewDWindow;
BEGIN
dispWind := GetNewWindow(resourceNum, NIL, behind);
SetUPDWindow;
GetNewDWindow := dispWind;
END;
{ ------------------------------------------------------------ }
{ Output Routines }
{ ------------------------------------------------------------ }
{}
{ Write text to display area if output is on (curDispWind != nil).}
{ DisplayText is the fundamental output routine. All other}
{ output calls map (eventually) to it.}
{ First check whether the insertion will cause overflow and flush}
{ out some stuff if so. Insert new text at the end, then test}
{ whether lines must be scrolled to get the new stuff to show up.}
{ If yes, then do the scroll. Set values of scroll bar properly}
{ and highlight as appropriate.}
{ The current port is preserved. Since all output calls end up}
{ here, it's the only output routine that has to save the port}
{ and check whether output is on.}
PROCEDURE DisplayText;
VAR
nLines, dispLines, topLines, scrollLines, lHeight : integer;
{ number of lines in TERec }
{ number of lines displayable in window }
{ number of lines currently scrolled off top }
{ number of lines to scroll up }
r : Rect;
savePort : GrafPtr;
dTE : TEHandle;
BEGIN
IF curDispWind <> NIL THEN
BEGIN
GetPort(savePort);
SetPort(curDispWind);
SyncGlobals(curDispWind);
dTE := dispTE;
IF dTE^^.teLength + len > dMaxText THEN { check overflow }
BEGIN
FlushDWindow(dispWind, dFlushAmt);
DisplayString('(autoflush occurred)');
END;
lHeight := dTE^^.lineHeight;
TESetSelect(longint(32767), longint(32767), dTE);
TEInsert(theText, len, dTE);
r := dTE^^.viewRect;
nLines := dTE^^.nLines;
dispLines := (r.bottom - r.top) DIV lHeight;
topLines := LinesOffTop;
scrollLines := nLines - (topLines + dispLines);
IF scrollLines > 0 THEN { must scroll up }
TEScroll(0, -lHeight * scrollLines, dTE); { scroll up }
topLines := nLines - dispLines;
IF (topLines >= 0) AND (GetCtlMax(dispScroll) <> topLines) THEN
BEGIN
SetCtlMax(dispScroll, topLines);
SetCtlValue(dispScroll, topLines);
END;
HiliteScroll;
SetPort(savePort);
END;
END;
{ Derived output routines:}
{ DisplayString Write (Pascal) string}
{ DisplayLong Write value of long integer}
{ DisplayInt Write value of integer}
{ DisplayChar Write character}
{ DisplayHexLong Write value of long integer in hex (8 digits)}
{ DisplayHexInt Write value of integer in hex (4 digits)}
{ DisplayHexChar Write value of character in hex (2 digit)}
{ DisplayBoolean Write boolean value}
{ DisplayLn Write carriage return}
PROCEDURE DisplayString;
VAR
myPtr : Ptr;
BEGIN
myPtr := Ptr(longint(@theStr) + 1);
DisplayText(myPtr, longint(theStr[0]));
END;
PROCEDURE DisplayLong;
VAR
s : Str255;
BEGIN
NumToString(l, s);
DisplayString(s);
END;
PROCEDURE DisplayInt;
BEGIN
DisplayLong(longint(i));
END;
PROCEDURE DisplayChar;
VAR
myPtr : Ptr;
BEGIN
myPtr := @c;
myPtr := Ptr(longint(myPtr) + 1);
DisplayText(myPtr, longint(1));
END;
PROCEDURE DisplayLn;
BEGIN
DisplayChar(char(13));
END;
PROCEDURE DisplayBoolean;
BEGIN
IF b THEN
DisplayString('True')
ELSE
DisplayString('False');
END;
PROCEDURE HexByte (value : integer); {value should be 0..15}
BEGIN
IF value < 10 THEN
DisplayChar(char(value + integer('0')))
ELSE
DisplayChar(char(value + (integer('a') - 10)));
END;
PROCEDURE DisplayHexChar;
BEGIN
HexByte(integer(BitAnd(BitShift(longint(c), -4), $0000000f)));
HexByte(integer(BitAnd(longint(c), $0000000f)));
END;
PROCEDURE DisplayHexInt;
BEGIN
DisplayHexChar(char(BitAnd(BitShift(longint(i), -8), $000000ff)));
DisplayHexChar(char(BitAnd(longint(i), $000000ff)));
END;
PROCEDURE DisplayHexLong;
BEGIN
DisplayHexInt(Integer(BitAnd(BitShift(l, -16), $0000ffff)));
DisplayHexInt(integer(BitAnd(l, $0000ffff)));
END;
PROCEDURE TransDisplayInit;
BEGIN
{ Default values for display window characteristics}
d_font := monaco; { default font }
d_size := 9; { default pointsize }
d_wrap := 0; { default word wrap (on) }
d_just := teJustLeft; { default justification }
d_maxText := 30000; { default max text allowed }
d_flushAmt := 25000; { default autoflush amount }
d_activate := NIL; { default notification proc }
{ Lowest allowable values for autoflush characteristics}
d_loMaxText := 100;
d_loFlushAmt := 100;
{ dwList points to a list of structures describing the known display}
{ windows.}
{ curDispWind is the current output window.}
{ If curDispWind = nil, output is currently turned off.}
dwList := NIL;
dispWind := NIL;
curDispWind := NIL;
END;
END.